package com.syh.jn.scm.domain.supplier.entity.purchase;

import cn.redscarf.commons.util.bean.ExtBeanUtils;
import cn.redscarf.commons.util.other.ExtAssert;
import cn.redscarf.commons.spring.SpringContextUtils;
import cn.redscarf.commons.util.validator.ValidationUtils;
import cn.redscarf.commons.wrapper.Restrictions;
import cn.redscarf.commons.wrapper.Wrapper;
import com.syh.core.ddd.domain.AbstractSimpleAggregate;
import com.syh.core.ddd.domain.CodeExpEnum;
import com.syh.core.ddd.domain.CodeGenerateUtil;
import com.syh.jn.scm.domain.supplier.entity.finance.OrderExpensesBill;
import com.syh.jn.scm.domain.supplier.entity.finance.OrderExpensesBillItem;
import com.syh.jn.scm.domain.supplier.entity.logistics.LogisticsBill;
import com.syh.jn.scm.domain.supplier.entity.logistics.LogisticsBillItem;
import com.syh.jn.scm.domain.supplier.entity.sale.SaleOrder;
import com.syh.jn.scm.domain.supplier.repository.finance.OrderExpensesBillReadRepository;
import com.syh.jn.scm.domain.supplier.repository.finance.OrderExpensesBillRepository;
import com.syh.jn.scm.domain.supplier.repository.logistics.LogisticsBillReadRepository;
import com.syh.jn.scm.domain.supplier.repository.purchase.PurchaseOrderReadRepository;
import com.syh.jn.scm.domain.supplier.repository.sale.SaleOrderReadRepository;
import com.syh.jn.scm.dto.supplier.purchase.PurchaseOrderMto;
import com.syh.jn.scm.dto.supplier.purchase.PurchaseOrderSto;
import com.syh.jn.scm.dto.support.FilesDto;
import com.syh.jn.scm.exception.BusinessException;
import com.syh.jn.scm.service.api.supplier.finance.enums.OrderExpensesBillEnums;
import com.syh.jn.scm.service.api.supplier.logistics.enums.LogisticsBillEnums;
import com.syh.jn.scm.service.api.supplier.purchase.enums.PurchaseOrderEnums;
import com.syh.jn.scm.service.api.supplier.sale.enums.SaleOrderEnums;
import lombok.AccessLevel;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;

/**
 * 采购单聚合
 */
@Data
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@EqualsAndHashCode(callSuper = true)
public class PurchaseOrder extends AbstractSimpleAggregate<Long> {

  public PurchaseOrder(PurchaseOrderSto sto) {
    ExtAssert.notNull(sto, "对象为空");
    ValidationUtils.validate(sto);
    //1.当选择了普通采购时,销售订单一定为空
    if (PurchaseOrderEnums.OrderType.COMMON_PURCHASE.getStatus().equals(sto.getOrderType())) {
      sto.setSalesOrderId(null);
    } else {
      //2.当选择了直采直销时,销售订单一定不能为空
      if (sto.getSalesOrderId() == null) {
        throw new BusinessException("销售订单不能为空");
      }
      //TODO 不限制直采直销单的生成
//      SaleOrderReadRepository saleOrderQuery = (SaleOrderReadRepository) SpringContextUtils.getBean(SaleOrderReadRepository.class);
//      PurchaseOrderReadRepository purchaseQuery = (PurchaseOrderReadRepository) SpringContextUtils.getBean(PurchaseOrderReadRepository.class);
//      int purchaseQueryCount = purchaseQuery.getCount(Wrapper.build().append(Restrictions.eq("salesOrderId", sto.getSalesOrderId())));
//      SaleOrder saleOrder = saleOrderQuery.getOne(Wrapper.build().append(Restrictions.eq("id", sto.getSalesOrderId())));
//      if (!saleOrder.getOrdState().equals(SaleOrderEnums.State.CONFIRM.getStatus())
//              && saleOrder.getDeliveryState().equals(SaleOrderEnums.DeliveryState.LOGISTICS_UN_DELIVERY.getStatus())) {
//        throw new BusinessException("该销售订单状态为已确认,物流状态为未发车才能生成采购单");
//      }
//      if (purchaseQueryCount > 0) {
//        throw new BusinessException("该销售订单已经生成过采购订单,请选择另外一张单");
//      }
    }
    super.initDefault();
    this.code = CodeGenerateUtil.codeGenerate(CodeExpEnum.PURCHASE_ORDER_EXP.getCodeExp(), sto.getUpStreamCompanyId());
    //优惠
    this.discount = BigDecimal.ZERO;
    //运费
    this.totalFreight = BigDecimal.ZERO;
    this.ordState = PurchaseOrderEnums.OrdState.STAYCONFIRM.getStatus();
    //未生成物流
    this.generatedState = PurchaseOrderEnums.GeneratedState.LOGISTICS_UN_GENERATE.getStatus();
    //未发车
    this.deliveryState = PurchaseOrderEnums.DeliveryState.LOGISTICS_UN_DELIVERY.getStatus();
    //未签收
    this.collectState = PurchaseOrderEnums.CollectState.LOGISTICS_UN_COLLECT.getStatus();

    ExtBeanUtils.copyProperties(sto, this, false);
    this.items = new ArrayList<>();
    sto.getItems().forEach(item -> {
      ExtAssert.notNull(item, "商品对象为空");
      ValidationUtils.validate(item);
      this.addItem(new PurchaseOrderItem(item));
    });
    //计算订单总额
    this.calculateTotalAmount();
  }

  /**
   * 计算订单总额、商品总额
   */
  private void calculateTotalAmount() {
    BigDecimal totalAmount = BigDecimal.ZERO;
    for (PurchaseOrderItem item : this.items) {
      totalAmount = totalAmount.add(item.getTotalAmount());
    }
    this.goodsTotalAmount = totalAmount;//商品总额
    //减去优惠价格
    if (this.discount != null) {
      totalAmount = totalAmount.subtract(this.discount);
    }
    //加上订单费用
    if (this.orderExpensesBillId != null) {
      totalAmount = totalAmount.add(this.otherExpenses);
    }
    //订单总额
    this.totalAmount = totalAmount;
  }

  /**
   * 计算订单入库总额、商品入库总额
   */
  private void calculateTotalInAmount() {
    //计算入库商品总额
    BigDecimal totalAmount = BigDecimal.ZERO;
    for (PurchaseOrderItem item : this.items) {
      totalAmount = totalAmount.add(item.calculateTotalInAmount());
    }
    this.totalInGoodsAmount = totalAmount;

    //先计算出该订单下已签收状态的物流单据的物流费用
    LogisticsBillReadRepository logisticsBillReadRepository = (LogisticsBillReadRepository) SpringContextUtils.getBean(LogisticsBillReadRepository.class);
    Wrapper we = Wrapper.build();
    we.append(Restrictions.eq("orderId", this.id));
    we.append(Restrictions.eq("orderType", LogisticsBillEnums.OrderType.PURCHASE.getStatus()));
    we.append(Restrictions.eq("logisticsState", LogisticsBillEnums.State.SIGNIN.getStatus()));
    List<LogisticsBill> logisticsBills = logisticsBillReadRepository.getList(we);

    BigDecimal logisticsBillBeforeBuyFreight = BigDecimal.ZERO;//物流单据为预收买家的所有物流费用
    for (LogisticsBill logisticsBill : logisticsBills) {
      if (logisticsBill.getFreightTake() != null && logisticsBill.getFreightTake().equals(LogisticsBillEnums.FreightTake.BUY.getStatus())
              && logisticsBill.getFreightType().equals(LogisticsBillEnums.FreightType.BEFORE.getStatus()))
        logisticsBillBeforeBuyFreight = logisticsBillBeforeBuyFreight.add(logisticsBill.getTotalFreight());
    }

    //加上预收买家的物流运费
    totalAmount = totalAmount.add(logisticsBillBeforeBuyFreight);
    //减去优惠价格
    if (this.discount != null) {
      totalAmount = totalAmount.subtract(this.discount);
    }
    //如果有费用表  加上费用表金额
    if (this.orderExpensesBillId != null) {
      totalAmount = totalAmount.add(this.otherExpenses);
    }
    //入库总额
    this.totalInAmount = totalAmount.compareTo(BigDecimal.ZERO) < 1?BigDecimal.ZERO:totalAmount;;
    this.lastUpdateTimeStamp = System.currentTimeMillis();
  }

  /**
   * 计算订单入库状态
   */
  private void calculateCollectStatus() {
    //默认为已完全签收
    this.collectState = PurchaseOrderEnums.CollectState.LOGISTICS_WHOLE_COLLECT.getStatus();
    //默认标记为未生成物流单
    boolean unCollected = true;

    for (PurchaseOrderItem item : this.items) {
      //订单项已生成数量小于订单数量则为部分生成物流单
      if(this.collectState.equals(PurchaseOrderEnums.CollectState.LOGISTICS_WHOLE_COLLECT.getStatus())
              && item.getInQuantity().compareTo(item.getQuantity()) < 0){
        this.collectState = PurchaseOrderEnums.CollectState.LOGISTICS_PART_COLLECT.getStatus();
      }
      //订单项已发货数量大于0 则不是未发货
      if ( unCollected && item.getInQuantity().compareTo(BigDecimal.ZERO) > 0 ) {
        unCollected = false;
      }
    }
    if (unCollected) {
      this.collectState = PurchaseOrderEnums.CollectState.LOGISTICS_UN_COLLECT.getStatus();
      this.storageTimestamp = null;
    }
  }

  /**
   * 增加订单项
   *
   * @param item
   * @return
   */
  public PurchaseOrder addItem(PurchaseOrderItem item) {
    if (this.items == null) {
      this.items = new ArrayList<>();
    }
    this.items.add(item);
    return this;
  }

  /**
   * 修改采购订单
   *
   * @param mto
   * @return
   */
  public void modify(PurchaseOrderMto mto) {
    ExtAssert.notNull(mto, "对象为空");
    ValidationUtils.validate(mto);
    if (!PurchaseOrderEnums.OrdState.STAYCONFIRM.getStatus().equals(this.getOrdState())) {
      throw new BusinessException("订单不在可修改状态!");
    }
    //1.当选择了普通采购时,销售订单一定为空
    if (PurchaseOrderEnums.OrderType.COMMON_PURCHASE.getStatus().equals(mto.getOrderType())) {
      mto.setSalesOrderId(null);
    } else {
      //2.当选择了直采直销时,销售订单一定不能为空
      if (mto.getSalesOrderId() == null) {
        throw new BusinessException("销售订单不能为空");
      }
      SaleOrderReadRepository saleOrderQuery = (SaleOrderReadRepository) SpringContextUtils.getBean("saleOrderRepositoryImpl");
      PurchaseOrderReadRepository purchaseQuery = (PurchaseOrderReadRepository) SpringContextUtils.getBean("purchaseOrderRepositoryImpl");
      int purchaseQueryCount = purchaseQuery.getCount(Wrapper.build().append(Restrictions.eq("salesOrderId", mto.getSalesOrderId())));
      SaleOrder saleOrder = saleOrderQuery.getOne(Wrapper.build().append(Restrictions.eq("id", mto.getSalesOrderId())));
      if (!saleOrder.getOrdState().equals(SaleOrderEnums.State.CONFIRM.getStatus())
              && saleOrder.getDeliveryState().equals(SaleOrderEnums.DeliveryState.LOGISTICS_UN_DELIVERY.getStatus())) {
        throw new BusinessException("该销售订单状态为已确认,物流状态为未发车才能生成采购单");
      }
      //当这张单的销售订单id和现在选择的销售订单id
      if (this.getSalesOrderId() != null && !this.getSalesOrderId().equals(mto.getSalesOrderId()) && purchaseQueryCount > 0) {
        throw new BusinessException("该销售订单已经生成过采购订单,请选择另外一张单");
      }
    }
    ExtBeanUtils.copyProperties(mto, this);
    this.lastUpdateTimeStamp = System.currentTimeMillis();
    this.items = new ArrayList<>();
    mto.getItems().stream().forEach(itemMto -> {
      ExtAssert.notNull(itemMto, "明细对象为空");
      ValidationUtils.validate(itemMto);
      this.addItem(new PurchaseOrderItem(itemMto));
    });
    //重新计算订单总额
    this.calculateTotalAmount();
  }

  /**
   * 删除订单
   */
  public void destroy() {
    if (!PurchaseOrderEnums.OrdState.STAYCONFIRM.getStatus().equals(this.ordState)
            && !PurchaseOrderEnums.OrdState.CANCEL.getStatus().equals(this.ordState)){
      throw new BusinessException("订单不是已取消状态或待确认状态,不可以删除");
    }
    if(this.haveRecord != null &&
            this.haveRecord.equals(PurchaseOrderEnums.OrdState.HAVE_RECORD.getStatus())){
      throw new BusinessException("订单已存在记录,不可以删除");
    }
  }

  /**
   * 确认收货
   */
  public void collect(LogisticsBill bill) {
    if (this.collectState.equals(PurchaseOrderEnums.CollectState.LOGISTICS_WHOLE_COLLECT.getStatus()))
      throw new BusinessException("签收失败，已全部签收！");
    //获取物流单据明细并计算订单项的已收货数量
    bill.getItems().forEach( logisticsBillItem -> {
      this.items.forEach(orderItem -> {
        if (orderItem.getId().equals(logisticsBillItem.getOrderItemId())) {
          orderItem.setInQuantity(orderItem.getInQuantity()==null?logisticsBillItem.getQuantity():
                  orderItem.getInQuantity().add(logisticsBillItem.getQuantity()));
        }
      });
    });

    this.haveRecord = PurchaseOrderEnums.OrdState.HAVE_RECORD.getStatus();
    this.storageTimestamp = System.currentTimeMillis();
    this.calculateTotalInAmount();
    this.calculateCollectStatus();
  }

  /**
   * 取消收货
   */
  public void cancelCollect(LogisticsBill bill) {
    if (this.collectState.equals(PurchaseOrderEnums.CollectState.LOGISTICS_UN_COLLECT.getStatus()))
      throw new BusinessException("取消签收失败，无签收记录！");
    //获取物流单据明细并计算订单项的已收货数量
    bill.getItems().forEach( logisticsBillItem -> {
      this.items.forEach(orderItem -> {
        if (orderItem.getId().equals(logisticsBillItem.getOrderItemId())) {
          if (orderItem.getGeneratedReturnQuantity() != null && orderItem.getGeneratedReturnQuantity().compareTo(BigDecimal.ZERO) > 0) {
            throw new BusinessException(orderItem.getGoodsName()+"已生成退货单，无法取消签收！");
          }
          orderItem.setInQuantity(orderItem.getInQuantity().subtract(logisticsBillItem.getQuantity()));
        }
      });
    });
    this.calculateTotalInAmount();
    this.calculateCollectStatus();
  }

  /**
   * 生成对账单
   */
  public void generating(Long statementOfAccountId) {
    if (this.collectState.equals(PurchaseOrderEnums.CollectState.LOGISTICS_UN_COLLECT.getStatus())) {
      throw new BusinessException("采购单"+this.code+"未签收，无法生成对账单");
    }
    if (PurchaseOrderEnums.OrdState.STATEMENT.getStatus().equals(this.ordState)) {
      throw new BusinessException("采购单已生成对账单!");
    }
    //如果有订单费用表
    if (this.orderExpensesBillId != null) {
      OrderExpensesBillReadRepository orderExpensesBillRepository = (OrderExpensesBillReadRepository) SpringContextUtils.getBean(OrderExpensesBillRepository.class);
      OrderExpensesBill orderExpensesBill = orderExpensesBillRepository.getById(this.orderExpensesBillId);
      //如果订单费用未确认 不允许生成对账单
      if (!orderExpensesBill.getState().equals(OrderExpensesBillEnums.State.CONFIRM.getStatus())) {
        throw new BusinessException("采购单"+this.code+"生成的费用表未确认。无法生成对账单！");
      }
    }
    this.statementId = statementOfAccountId;
    this.ordState = PurchaseOrderEnums.OrdState.STATEMENT.getStatus();
  }

  /**
   * 取消对账单状态
   */
  public void cancelStatementState() {
    this.statementId = null;
    this.ordState = PurchaseOrderEnums.OrdState.CONFIRM.getStatus();
  }

  /**
   * 订单取消
   */
  public void cancel() {
    //只有订单为待确认的时候才可以取消
    if (!PurchaseOrderEnums.OrdState.STAYCONFIRM.getStatus().equals(this.ordState)) {
      throw new BusinessException("订单不是待确认状态,不可以取消");

    }
    this.ordState = PurchaseOrderEnums.OrdState.CANCEL.getStatus();
  }

  /**
   * 上传图片
   *
   * @param dto
   */
  public void uploadImages(FilesDto dto) {
    this.mainSrcImages = dto.getFiles();
  }

  /**
   * 确认
   */
  public void confirm() {
    if (!PurchaseOrderEnums.OrdState.STAYCONFIRM.getStatus().equals(this.ordState)) {
      throw new BusinessException("订单不是待确认状态,不能确认订单");
    }
    this.ordState = PurchaseOrderEnums.OrdState.CONFIRM.getStatus();
  }

  /**
   * 保存订单费用表
   * @param orderExpensesBillId
   */
  public void addExpensesBill(Long orderExpensesBillId) {
    if (this.ordState.equals(PurchaseOrderEnums.OrdState.STATEMENT.getStatus())) {
      throw new BusinessException("采购单已生成对账单！保存失败！");
    }
    if (this.orderExpensesBillId != null && !this.orderExpensesBillId.equals(orderExpensesBillId)) {
      throw new BusinessException("采购单已有费用表！保存失败！");
    }
    this.orderExpensesBillId = orderExpensesBillId;
    this.otherExpenses = BigDecimal.ZERO;
  }
  /**
   * 删除订单费用表
   * @param orderExpensesBillId
   */
  public void deletedExpensesBill(Long orderExpensesBillId) {
    if (this.ordState.equals(PurchaseOrderEnums.OrdState.STATEMENT.getStatus())) {
      throw new BusinessException("采购单已生成对账单！删除失败！");
    }
    if (!this.orderExpensesBillId.equals(orderExpensesBillId)) {
      throw new BusinessException("采购单与费用表不匹配！删除失败！");
    }
    this.orderExpensesBillId = null;
  }

  /**
   * 确认订单费用
   * @param orderExpensesBill
   */
  public void confirmExpensesBill(OrderExpensesBill orderExpensesBill) {
    //如果采购单未生成记录(即未签收过货) 不允许确认费用
    if (!this.haveRecord.equals(PurchaseOrderEnums.OrdState.HAVE_RECORD.getStatus())) {
      throw new BusinessException("采购单未签收过货！确认费用失败！");
    }
    if (this.ordState.equals(PurchaseOrderEnums.OrdState.STATEMENT.getStatus())) {
      throw new BusinessException("采购单已生成对账单！确认费用失败！");
    }
    if (!this.orderExpensesBillId.equals(orderExpensesBill.getId())) {
      throw new BusinessException("采购单与费用表不匹配！确认费用失败！");
    }
    this.countExpenses(orderExpensesBill);
  }
  /**
   * 取消订单费用
   * @param orderExpensesBill
   */
  public void cancelExpensesBill(OrderExpensesBill orderExpensesBill) {
    if (this.ordState.equals(PurchaseOrderEnums.OrdState.STATEMENT.getStatus())) {
      throw new BusinessException("采购单已生成对账单！取消费用失败！");
    }
    if (!this.orderExpensesBillId.equals(orderExpensesBill.getId())) {
      throw new BusinessException("采购单与费用表不匹配！取消费用失败！");
    }
    this.otherExpenses = BigDecimal.ZERO;
    this.calculateTotalAmount();
    this.calculateTotalInAmount();
  }

  /**
   * 把我方承担费用算入订单总额
   */
  private void countExpenses(OrderExpensesBill orderExpensesBill){
    this.otherExpenses = BigDecimal.ZERO;
    if (orderExpensesBill.getItems() != null) {
      for (OrderExpensesBillItem expensesBillItem: orderExpensesBill.getItems()) {
        //计算纳入总额费用
        if (expensesBillItem.getIncludeTotalAmount().equals(OrderExpensesBillEnums.IncludeTotalAmount.INCLUDE.getStatus())) {
          this.otherExpenses = this.otherExpenses.add(expensesBillItem.getExpenses());
        }
      }
    }
    //重新计算订单总额
    this.calculateTotalAmount();
    //如果已收货
    if (!this.deliveryState.equals(PurchaseOrderEnums.CollectState.LOGISTICS_UN_COLLECT.getStatus())) {
      //重新计算订单签收总额
      this.calculateTotalInAmount();
    }
  }


  /**
   * 纠正订单物流相关字段数据（在订单项outedQuantity和inQuantity字段数据正确的情况下）
   * @param logisticsBillItems
   */
  public void correctingLogisticsData(List<LogisticsBillItem> logisticsBillItems) {
    //订单项generateQuantity字段初始为已发货数量
    this.items.forEach(item-> {
      item.setGeneratedQuantity(item.getOutedQuantity() == null ? BigDecimal.ZERO : item.getOutedQuantity());
      //添加未发货物流订单项商品数量
      logisticsBillItems.forEach(logisticsBillItem -> {
        if (item.getId().equals(logisticsBillItem.getOrderItemId())) {
          item.setGeneratedQuantity(item.getGeneratedQuantity().add(logisticsBillItem.getQuantity()));
        }
      });
    });
    //默认为已完全签收
    this.collectState = SaleOrderEnums.CollectState.LOGISTICS_WHOLE_COLLECT.getStatus();
    //默认标记为未签收
    boolean unCollected = true;
    this.deliveryState = SaleOrderEnums.DeliveryState.LOGISTICS_WHOLE_DELIVEED.getStatus();
    //默认标记为未发货
    boolean unDelivery = true;
    //默认为已完全生成物流单
    this.generatedState = SaleOrderEnums.GeneratedState.LOGISTICS_WHOLE_GENERATE.getStatus();
    //默认标记为未生成物流单
    boolean unGenerated = true;

    for (PurchaseOrderItem item : this.items) {
      //订单项已生成数量小于订单数量则为部分生成物流单
      if(this.collectState.equals(SaleOrderEnums.CollectState.LOGISTICS_WHOLE_COLLECT.getStatus())
              && (item.getInQuantity() == null || item.getInQuantity().compareTo(item.getQuantity()) < 0)){
        this.collectState = SaleOrderEnums.CollectState.LOGISTICS_PART_COLLECT.getStatus();
      }
      //订单项已发货数量大于0 则不是未发货
      if ( unCollected && (item.getInQuantity() != null && item.getInQuantity().compareTo(BigDecimal.ZERO) > 0 )) {
        unCollected = false;
      }
      //订单项已发货数量小于订单数量则为部分发货
      if(this.deliveryState.equals(SaleOrderEnums.DeliveryState.LOGISTICS_WHOLE_DELIVEED.getStatus())
              && (item.getOutedQuantity() == null || item.getOutedQuantity().compareTo(item.getQuantity()) < 0)){
        this.deliveryState = SaleOrderEnums.DeliveryState.LOGISTICS_PART_DELIVEED.getStatus();
      }
      //订单项已发货数量大于0 则不是未发货
      if ( unDelivery && (item.getOutedQuantity() != null && item.getOutedQuantity().compareTo(BigDecimal.ZERO) > 0 )) {
        unDelivery = false;
      }
      //订单项已生成数量小于订单数量则为部分生成物流单
      if(this.generatedState.equals(SaleOrderEnums.GeneratedState.LOGISTICS_WHOLE_GENERATE.getStatus())
              && item.getGeneratedQuantity().compareTo(item.getQuantity()) < 0){
        this.generatedState = SaleOrderEnums.GeneratedState.LOGISTICS_PART_GENERATE.getStatus();
      }
      //订单项已发货数量大于0 则不是未发货
      if ( unGenerated && item.getGeneratedQuantity().compareTo(BigDecimal.ZERO) > 0 ) {
        unGenerated = false;
      }
    }
    if (unCollected) {
      this.collectState = SaleOrderEnums.CollectState.LOGISTICS_UN_COLLECT.getStatus();
    }
    if (unDelivery) {
      this.deliveryState = SaleOrderEnums.DeliveryState.LOGISTICS_UN_DELIVERY.getStatus();
    }
    if (unGenerated) {
      this.generatedState = SaleOrderEnums.GeneratedState.LOGISTICS_UN_GENERATE.getStatus();
    }
  }

  /**
   * 创建退货单 记录退货数量
   * @param returnOrder 退货单
   */
  public void createdReturnOrder(PurchaseReturnOrder returnOrder) {
    this.addGeneratedReturnQuantity(returnOrder);
  }

  /**
   * 修改退货单 记录退货数量
   * @param returnOrder 退货单
   * @param oldReturnOrder 旧退货单
   */
  public void updatedReturnOrder(PurchaseReturnOrder returnOrder,PurchaseReturnOrder oldReturnOrder) {
    this.subGeneratedReturnQuantity(oldReturnOrder);
    this.addGeneratedReturnQuantity(returnOrder);
  }

  /**
   * 取消退货单 记录退货数量
   * @param returnOrder 退货单
   */
  public void cancelReturnOrder(PurchaseReturnOrder returnOrder) {
    this.subGeneratedReturnQuantity(returnOrder);
  }

  /**
   * 添加退货数量
   * @param returnOrder
   */
  private void addGeneratedReturnQuantity(PurchaseReturnOrder returnOrder) {
    returnOrder.getItems().forEach(returnOrderItem -> {
      this.items.forEach(orderItem->{
        if (orderItem.getId().equals(returnOrderItem.getOrderItemId())) {
          //记录退货数量
          orderItem.setGeneratedReturnQuantity(orderItem.getGeneratedReturnQuantity() == null ? returnOrderItem.getReturnQuantity() : orderItem.getGeneratedReturnQuantity().add(returnOrderItem.getReturnQuantity()));
          //判断退货数量是否大于签收数量
          if (orderItem.getGeneratedReturnQuantity().compareTo(orderItem.getInQuantity()) > 0) {
            BigDecimal returnQuantity = orderItem.getGeneratedReturnQuantity().subtract(returnOrderItem.getReturnQuantity());
            throw new BusinessException("退货数量不能大于签收数量！"+orderItem.getGoodsName()+"已签收"+orderItem.getInQuantity()+" 已生成退货："+returnQuantity);
          }
        }
      });
    });
  }

  /**
   * 减少退货数量
   * @param returnOrder
   */
  private void subGeneratedReturnQuantity(PurchaseReturnOrder returnOrder) {
    returnOrder.getItems().forEach(returnOrderItem -> {
      this.items.forEach(orderItem->{
        if (orderItem.getId().equals(returnOrderItem.getOrderItemId())) {
          //回退退货数量
          orderItem.setGeneratedReturnQuantity(orderItem.getGeneratedReturnQuantity().subtract(returnOrderItem.getReturnQuantity()));
          //判断回退后的数量是否小于0  正常情况不应该小于0
          if (orderItem.getGeneratedReturnQuantity().compareTo(BigDecimal.ZERO) < 0) {
            throw new BusinessException("服务异常，请联系客服！");
          }
        }
      });
    });
  }


  /**
   * 归属于那个服务商
   */
  private Long businessEntityId;
  /**
   * 采购订单编号
   */
  private String code;
  /**
   * 采购订单类型(0：普通采购 1：直采直销 )
   */
  private Short orderType;
  /**
   * 销售订单id(当选择了直采直销时)
   */
  private Long salesOrderId;
  /**
   * 第三方订单号
   */
  private String extCode;
  /**
   * 上游单位的id
   */
  private Long upStreamCompanyId;
  /**
   * 采购订单状态(0：待确认 1：已确认 2：挂起 3：已生成对账单 -1：已取消)
   */
  private Short ordState;
  /**
   * 收货人姓名
   */
  private String deliName;
  /**
   * 收货人联系电话
   */
  private String deliTel;
  /**
   * 要求到货时间
   */
  private Long receiveTimestamp;
  /**
   * 收货地区编码
   */
  private String deliAreaCode;
  /**
   * 收货地址省 市 区
   */
  private String deliArea;
  /**
   * 收货人详细地址
   */
  private String deliAddress;
  /**
   * 发货地区编码
   */
  private String upDeliAreaCode;
  /**
   * 发货地址省 市 区
   */
  private String upDeliArea;
  /**
   * 发货人详细地址
   */
  private String upDeliAddress;
  /**
   * 订单备注
   */
  private String remark;
  /**
   * 优惠金额
   */
  private BigDecimal discount;
  /**
   * 订单总额
   */
  private BigDecimal totalAmount;
  /**
   * 入库总额
   */
  private BigDecimal totalInAmount;
  /**
   * 入库商品总额
   */
  private BigDecimal totalInGoodsAmount;
  //TODO 上游出库总额字段预计以后要删除
  /**
   * 出库总额
   */
  private BigDecimal totalOutAmount;
  //TODO 上游出库商品总额字段预计以后要删除
  /**
   * 出库商品总额
   */
  private BigDecimal totalOutGoodsAmount;
  /**
   * 运费金额
   */
  private BigDecimal totalFreight;
  /**
   * 商品总额
   */
  private BigDecimal goodsTotalAmount;
  /**
   * 录单日期
   */
  private Long inputDateTimestamp;
  /**
   * 发货时间
   */
  private Long deliveryTimestamp;
  /**
   * 入库时间(收货)
   */
  private Long storageTimestamp;
  /**
   * 录单人员id
   */
  private Long operatorId;
  /**
   * 订单账期
   */
  private Integer accountPeriod;
  /**
   * 物流生成状态(0：未生成物流单 1：部分生成物流单2：完成生成物流单)
   */
  private Short generatedState;
    /**
     * 发货状态(0：未发货 1：部分发货 2：完成发货)
     */
  private Short deliveryState;
  /**
   * 签收状态(0：未签收 1：部分签收 2：完成签收)
   */
  private Short collectState;
  /**
   * 对账单id
   */
  private Long statementId;
  /**
   * 对方单据图片
   */
  private String secondSrcImages;
  /**
   * 我方销售单图片
   */
  private String mainSrcImages;
  /**
   * 是否已生成记录(库存记录、应收付记录等) 0:未生成 1：已生成
   */
  private Short haveRecord;
  /**
   * 订单费用表id
   */
  private Long orderExpensesBillId;
  /**
   * 其他费用
   */
  private BigDecimal otherExpenses;
  /**
   * 采购订单明细
   */
  protected List<PurchaseOrderItem> items;
}
